import ListItem from "./ListItem";

export enum Layout {
    HORIZONTAL,
    VERTICAL,
    GRID
}
enum TemplateType {
    NODE = 1,
    PREFAB = 2,
}
const { ccclass, property } = cc._decorator;

@ccclass
export default class ListView extends cc.Component {
    @property(cc.Node)
    content: cc.Node = null;
    @property({ type: cc.Enum(TemplateType), tooltip: CC_DEV && '模板类型', })
    private templateType: TemplateType = TemplateType.NODE;
    //模板Item（Node）
    @property({
        type: cc.Node,
        tooltip: CC_DEV && '模板Item',
        visible() { return this.templateType == TemplateType.NODE; }
    })
    tmpNode: cc.Node = null;
    //模板Item（Prefab）
    @property({
        type: cc.Prefab,
        tooltip: CC_DEV && '模板Item',
        visible() { return this.templateType == TemplateType.PREFAB; }
    })
    tmpPrefab: cc.Prefab = null;

    /**
     * HORIZONTAL表示横向滚动，单行排列，纵向居中
     * VERTICAL 表示纵向滚动，单列排列，横向居中
     * GRID表示纵向滚动，矩形阵列排布，横向居中
    */
    @property({ type: cc.Enum(Layout) })
    layout: Layout = Layout.VERTICAL;
    @property
    top:number = 0;
    @property
    buttom:number = 0;
    @property
    spaceY: number = 0;
    @property
    spaceX: number = 0;

    private horizontalCount: number = 1;
    private verticalCount: number = 1;
    private startIndex: number = 0;
    private endIndex: number = 0;
    private scroll: cc.ScrollView = null;

    private _array: any[];
    public get array() {
        return this._array;
    }
    public set array(arr: any[]) {
        this._array = arr;
        this.setLayout();
        //this.setData();
        this.onScrolling();
    }
    canSeeNode: cc.Node[] = [];
    onLoad() {
        this.scroll = this.node.getComponent(cc.ScrollView);
        let layout = this.content.getComponent(cc.Layout);
        if (layout)
            this.content.removeComponent(cc.Layout);
        this.content.position = cc.v3(0, 0);
    }
    private setLayout() {

        if (this.templateType == TemplateType.PREFAB) {
            this.tmpNode = cc.instantiate(this.tmpPrefab);
        }
        switch (this.layout) {
            case Layout.HORIZONTAL:
                this.scroll.horizontal = true;
                this.scroll.vertical = false;
                this.verticalCount = 1;
                this.horizontalCount = Math.ceil(this.node.width / (this.spaceX + this.tmpNode.width)) + 1;
                this.content.height = this.node.height;
                this.content.width = (this.spaceX + this.tmpNode.width) * this._array.length;
                if (this.content.width <= this.node.width)
                    this.unregisterEvent();
                else
                    this.registerEvent();
                break;

            case Layout.VERTICAL:
                this.scroll.horizontal = false;
                this.scroll.vertical = true;
                this.horizontalCount = 1;
                this.verticalCount = Math.ceil(this.node.height / (this.tmpNode.height+this.spaceY)) + 1;
                this.content.width = this.node.width;
                this.content.height = (this.spaceY + this.tmpNode.height) * this._array.length - this.top - this.buttom;
                if (this.content.height <= this.node.height)
                    this.unregisterEvent();
                else
                    this.registerEvent();
                break;
            case Layout.GRID:
                this.scroll.horizontal = false;
                this.scroll.vertical = true;
                this.horizontalCount = Math.floor(this.node.width / (this.tmpNode.width + this.spaceX));
                this.verticalCount = Math.ceil(this.node.height / (this.spaceY + this.tmpNode.height)) + 1;
                this.content.width = this.node.width;
                this.content.height = (this.spaceY + this.tmpNode.height) * Math.ceil(this._array.length / this.horizontalCount) - this.top - this.buttom;
                if (this.content.height <= this.node.height)
                    this.unregisterEvent();
                else
                    this.registerEvent();
                break;
        }
        this.startIndex = 0;
        this.endIndex = this.horizontalCount * this.verticalCount;

    }

    private setData() {
        for (let index = this.startIndex; index <= this.endIndex; index++) {
            let newNode = this.canSeeNode[index - this.startIndex];
            if (!newNode) {
                newNode = cc.instantiate(this.tmpNode);
                this.content.addChild(newNode);
                this.canSeeNode.push(newNode);
            }
            this.setItemsPos(newNode, index);
            let item = newNode.getComponent(ListItem);
            if (this._array[index]) {
                item.dataChanged(this._array[index],index);
                newNode.active = true;
            } else {
                newNode.active = false;
            }

        }
    }
    private setItemsPos(node: cc.Node, index) {
        switch (this.layout) {
            case Layout.HORIZONTAL:
                node.y = -(this.node.height / 2 - node.height / 2);
                node.x = index * (this.spaceX + node.width);
                break;

            case Layout.VERTICAL:
                node.x = this.node.width / 2 - node.width / 2;
                node.y = -index * (this.spaceY + node.height)- this.top;
                break;
            case Layout.GRID:
                let w = index % this.horizontalCount;
                let h = Math.floor(index / this.horizontalCount);
                let edge = (this.node.width - this.horizontalCount * node.width - (this.horizontalCount - 1) * this.spaceX) / 2;
                node.x = edge + w * (node.width + this.spaceX);
                node.y = -h * (node.height + this.spaceY)- this.top;
                break;
        }
    }
    public onEnable() {
        this.registerEvent();
    }

    public onDisable() {
        this.unregisterEvent();
    }
    //注册事件
    private registerEvent() {
        let handler = new cc.Component.EventHandler();
        handler.target = this.node;
        handler.handler = "onScrolling";
        handler.component = "ZSList";
        this.scroll.scrollEvents[0] = handler;
    }
    //卸载事件
    private unregisterEvent() {
        this.scroll.scrollEvents.length = 0;
    }

    public onScrolling(ev: cc.Event = null) {
        let currentIndex;
        switch (this.layout) {
            case Layout.HORIZONTAL:
                currentIndex = Math.floor(-this.content.x / (this.tmpNode.width + this.spaceX));
                if (currentIndex > this.startIndex) {
                    let node = this.canSeeNode.shift();
                    this.canSeeNode.push(node);
                }
                break;

            case Layout.VERTICAL:
                currentIndex = Math.floor(this.content.y / (this.tmpNode.height + this.spaceY));
                if (currentIndex > this.startIndex) {
                    let node = this.canSeeNode.shift();
                    this.canSeeNode.push(node);
                }
                break;
            case Layout.GRID:
                currentIndex = Math.floor(this.content.y / (this.tmpNode.height + this.spaceY)) * this.horizontalCount;
                if (currentIndex > this.startIndex) {
                    for (let index = this.startIndex; index < currentIndex; index++) {
                        let node = this.canSeeNode.shift();
                        this.canSeeNode.push(node);
                    }
                }
                break;
        }
        this.endIndex = currentIndex + this.endIndex - this.startIndex;
        this.startIndex = currentIndex;
        this.setData();
    }
    public refresh(){
        this.setData();
    }
}
